﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using GNF.GPS.ROYALTEK.Communication;
using System.Threading;

namespace GNF.GPS.ROYALTEK
{
    /// <summary>
    /// manage serial communication
    /// </summary>
    public class SerialCommunicationManager
    {

        #region const 

        public const string COM = "COM";

        public const int DefualtBaudRate = 4800;
        public const Parity DefualtParity = Parity.None;
        public const StopBits DefualtStopBits = StopBits.One;
        public const int DefualtDataBits = 8;
        public const int DefualtComNumber = 1;
        public const string NewLine = "\r\n";
        #endregion

        #region static

        public static string[] GetAvailablePortsNames()
        {
            return SerialPort.GetPortNames();
        }

        #endregion

        #region private and protected memebers

        protected SerialPort _port = new SerialPort();

        protected int _baudRate = DefualtBaudRate;
        protected Parity _parity = DefualtParity;
        protected StopBits _stopBits = DefualtStopBits;
        protected int _dataBits = DefualtDataBits;
        protected int _portName = DefualtComNumber;

        #endregion

        #region construction and init

        public SerialCommunicationManager(int portNumber) : this(portNumber, DefualtBaudRate, DefualtParity, DefualtStopBits, DefualtDataBits) { }

        public SerialCommunicationManager(int portNumber, int baudRate, Parity parity, StopBits stopBits, int DataBits)
        {
            #region port run params
            _portName = portNumber;
            _baudRate = baudRate;
            _parity = parity;
            _stopBits = stopBits;
            _dataBits = DataBits;

            #endregion

            #region port params

            //_port.NewLine = NewLine;
            //_port.ReceivedBytesThreshold = _dataBits;

            #endregion
            _port.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(_port_DataReceived);
        }

    
        #endregion

        #region public properties

        /// <summary>
        /// return true if the port is open
        /// </summary>
        public bool IsPortOpen
        {
            get
            {
                return _port.IsOpen;
            }
        }

        #endregion

        #region public methods

        /// <summary>
        /// open the port to the device
        /// </summary>
        /// <returns></returns>
        public bool OpenPort()
        {
            try
            {
                //first check if the port is already open
                //if its open then close it
                if (_port.IsOpen == true) _port.Close();

                //set the properties of our SerialPort Object
                _port.BaudRate = _baudRate;
                _port.DataBits = _dataBits;
                _port.StopBits = _stopBits;
                _port.Parity = _parity;
                _port.PortName = COM + _portName;
                
                //now open the port
                _port.Open();
                   
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// close the port to the device
        /// </summary>
        /// <returns></returns>
        public bool ClosePort()
        {
            try
            {
                _port.Close();
                return true;
            }
            catch
            {
                return false;
            }

        }

        /// <summary>
        /// send a message to the device
        /// </summary>
        /// <param name="msg">the message to send</param>
        /// <returns></returns>
        public bool SendMsg(string msg)
        {
            return true;
        }

        #endregion

        #region events and events handlers

        /// <summary>
        /// fire when a new data has arrived
        /// </summary>
        public event DataReceivedEventHandler DataReceived;

        /// <summary>
        /// take the data from the port when a new data arrive
        /// </summary>
        void _port_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            //read data waiting in the buffer
            string msg = _port.ReadLine();
            //System.Threading.Thread.CurrentThread
            //fire the data received event to all lisnters
            if (DataReceived != null)
            {
                ThreadPool.QueueUserWorkItem(
                    new WaitCallback(obj => DataReceived(this, new DataReceivedEventArgs(msg) )));
            }
        }


        #endregion

    }


}


